﻿// <copyright file="PlayerBase.cs" company="ALCPU">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Arthur Liberman</author>
// <email>Arthur_Liberman@hotmail.com</email>
// <date>03-30-2010</date>
// <summary>Contains Player class definition.</summary>

namespace ChessDefinitions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// A chess player
    /// </summary>
    public abstract class PlayerBase
    {
        /// <summary>
        /// Represents the players color.
        /// </summary>
        private readonly IPieceColor color;

        /// <summary>
        /// Holds all player's pieces.
        /// </summary>
        private List<IPiece> pieceList = new List<IPiece>();

        /// <summary>
        /// Initializes a new instance of the <see cref="PlayerBase"/> class.
        /// </summary>
        /// <param name="color">The color of the player's pieces.</param>
        public PlayerBase(IPieceColor color)
        {
            this.color = color;
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="PlayerBase"/> class from being created.
        /// </summary>
        private PlayerBase()
        {
        }

        /// <summary>
        /// Occurs when there is a player related event.
        /// </summary>
        public event PlayerEvent GameEvent;

        /// <summary>
        /// Gets the player's color.
        /// </summary>
        /// <value>The color.</value>
        public IPieceColor Color
        {
            get { return this.color; }
        }

        /// <summary>
        /// Gets the piece list.
        /// </summary>
        /// <value>The piece list.</value>
        public List<IPiece> PieceList
        {
            get { return this.pieceList; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this turn is active.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this turn is active; otherwise, <c>false</c>.
        /// </value>
        public bool IsTurnActive { get; protected set; }

        /// <summary>
        /// Starts the turn.
        /// </summary>
        public abstract void StartTurn();

        /// <summary>
        /// Ends the current turn.
        /// </summary>
        public abstract void EndTurn();

        /// <summary>
        /// Handles the user input.
        /// </summary>
        /// <param name="eventArgs">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        public abstract void HandleUserInput(EventArgs eventArgs);

        /// <summary>
        /// Checks the endgame.
        /// </summary>
        /// <param name="oppositePlayer">The opposite player.</param>
        /// <returns>
        ///     <c>GameEventType.None</c> if there were no threats from either side.
        ///     <c>GameEventType.Check</c> if there was a check from the opposing side.
        ///     <c>GameEventType.Checkmate</c> if there was a checkmate from the opposing side.
        ///     <c>GameEventType.Stalemate</c> if there is a stalemate.
        /// </returns>
        public virtual GameEventType CheckEndgame(PlayerBase oppositePlayer)
        {
            int moveCount = 0;
            GameEventType gameEvent = GameEventType.None;

            if (oppositePlayer == null)
            {
                throw new Exception("oppositePlayer can not be null");
            }

            foreach (IPiece piece in oppositePlayer.PieceList)
            {
                moveCount += piece.AllMoveOptions.Count;
            }

            if (moveCount == 0)
            {
                gameEvent = GameEventType.NoLegalMoves;
            }

            return gameEvent;
        }

        /// <summary>
        /// Notifies the game of an event.
        /// </summary>
        /// <param name="sender">The cause of the event.</param>
        /// <param name="gameEventType">Type of the game event.</param>
        protected void NotifyOfGameEvent(PlayerBase sender, GameEventType gameEventType)
        {
            if (this.GameEvent != null)
            {
                GameEventArgs<PlayerBase> gameEventArgs = new GameEventArgs<PlayerBase>(sender, gameEventType);

                foreach (PlayerEvent subscriber in this.GameEvent.GetInvocationList())
                {
                    try
                    {
                        subscriber(this, gameEventArgs);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
        }
    }
}